Imports Microsoft.Vbe.Interop

''' <summary>
''' Represents operations that can be made on a Visual Basic Extensibility object
''' </summary>
''' <remarks></remarks>
Public Class VBProjectOperations

    ' The VB Project we're acting on
    Private _ProjectProvider As IVBProjectProvider
    Private _Project As VBProject

#Region "Constructors"

    ''' <summary>
    ''' Default constructor
    ''' </summary>
    ''' <param name="vbProjectProvider">The project provider we're working with</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal vbProjectProvider As IVBProjectProvider)

        ' Check arguments
        If vbProjectProvider Is Nothing Then

            Throw New ArgumentNullException("vbProjectProvider")

        End If


        ' Record the values
        _ProjectProvider = vbProjectProvider
        _Project = _ProjectProvider.GetVBProject()

        ' Make sure we have a reference to the VB project
        If _Project Is Nothing Then

            Throw New Exception("Unable to get reference to the VBA project")

        End If


    End Sub

#End Region

#Region "Decompliation"

    Public Sub Decompile(ByVal destPath As String)

        ' Local Variables
        Dim strFileName As String

        ' Make sure the destination directory exists
        If Not IO.Directory.Exists(destPath) Then

            Throw New IO.DirectoryNotFoundException(String.Format("Cannot find output path {0}", destPath))

            ' TODO: Also check directory security


        End If

        ' Loop around and export all the components
        For Each component As VBComponent In _Project.VBComponents

            ' Get the filename
            strFileName = IO.Path.Combine(destPath, component.Name)
            strFileName = IO.Path.ChangeExtension(strFileName, GetFileExtension(component.Type))

            ' Export the file
            Try

                component.Export(strFileName)

            Catch ex As Exception

                Throw New Exception(String.Format("Unable to export component '{0}' to '{1}'", component.Name, strFileName), ex)

            End Try

        Next component

    End Sub


#End Region

#Region "General Utilities"

    ''' <summary>
    ''' Returns the file extension for the given component type
    ''' </summary>
    ''' <param name="componentType">The component type to get the extension for</param>
    ''' <returns>The file extension string</returns>
    Private Function GetFileExtension(ByVal componentType As vbext_ComponentType) As String

        Select Case componentType

            Case vbext_ComponentType.vbext_ct_StdModule

                Return "bas"

            Case vbext_ComponentType.vbext_ct_ClassModule

                Return "cls"

            Case vbext_ComponentType.vbext_ct_MSForm

                Return "frm"

            Case vbext_ComponentType.vbext_ct_ActiveXDesigner

                ' TODO: Does FRX fit here?
                Return "frx"

            Case Else

                ' TODO: Test all options
                Return "vba"

        End Select


    End Function
#End Region

End Class



''' <summary>
''' Implemeted by objects that provide access to the Visual Basic Extensibility object
''' </summary>
''' <remarks>Implemented to get access to the VBE project of VBA application hosts such as 
''' Word or Excel</remarks>
Public Interface IVBProjectProvider

    Function GetVBProject() As Microsoft.Vbe.Interop.VBProject

End Interface